home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / Berkeley DB 1.6 / recno / rec_open.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-18  |  6.4 KB  |  240 lines  |  [TEXT/????]

  1. /*-
  2.  * Copyright (c) 1990, 1993
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Mike Olson.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #if defined(LIBC_SCCS) && !defined(lint)
  38. static char sccsid[] = "@(#)rec_open.c    8.1 (Berkeley) 6/4/93";
  39. #endif /* LIBC_SCCS and not lint */
  40.  
  41. #include <sys/types.h>
  42. #ifndef macintosh
  43. #include <sys/mman.h>
  44. #endif
  45. #include <sys/stat.h>
  46.  
  47. #ifdef macintosh
  48. #include <sys/fcntl.h>
  49. #endif
  50.  
  51. #include <errno.h>
  52. #include <fcntl.h>
  53. #include <limits.h>
  54. #include <stddef.h>
  55. #include <stdio.h>
  56. #ifdef macintosh
  57. FILE * fdopen(int fd, char * mode);
  58. #else 
  59. #include <unistd.h>
  60. #endif
  61.  
  62. #include <db.h>
  63. #include "recno.h"
  64.  
  65. DB *
  66. __rec_open(fname, flags, mode, openinfo)
  67.     const char *fname;
  68.     int flags, mode;
  69.     const RECNOINFO *openinfo;
  70. {
  71.     BTREE *t;
  72.     BTREEINFO btopeninfo;
  73.     DB *dbp;
  74.     PAGE *h;
  75.     struct stat sb;
  76.     int rfd, sverrno;
  77.  
  78.     /* Open the user's file -- if this fails, we're done. */
  79. #ifdef macintosh
  80.     if (fname != NULL && (rfd = open(fname, flags)) < 0)
  81. #else
  82.     if (fname != NULL && (rfd = open(fname, flags, mode)) < 0)
  83. #endif
  84.         return (NULL);
  85.  
  86.     /* Create a btree in memory (backed by disk). */
  87.     dbp = NULL;
  88.     if (openinfo) {
  89.         if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
  90.             goto einval;
  91.         btopeninfo.flags = 0;
  92.         btopeninfo.cachesize = openinfo->cachesize;
  93.         btopeninfo.maxkeypage = 0;
  94.         btopeninfo.minkeypage = 0;
  95.         btopeninfo.psize = openinfo->psize;
  96.         btopeninfo.compare = NULL;
  97.         btopeninfo.prefix = NULL;
  98.         btopeninfo.lorder = openinfo->lorder;
  99.         dbp = __bt_open(openinfo->bfname,
  100.             O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo);
  101.     } else
  102.         dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL);
  103.     if (dbp == NULL)
  104.         goto err;
  105.  
  106.     /*
  107.      * Some fields in the tree structure are recno specific.  Fill them
  108.      * in and make the btree structure look like a recno structure.  We
  109.      * don't change the bt_ovflsize value, it's close enough and slightly
  110.      * bigger.
  111.      */
  112.     t = dbp->internal;
  113.     if (openinfo) {
  114.         if (openinfo->flags & R_FIXEDLEN) {
  115.             SET(t, R_FIXLEN);
  116.             t->bt_reclen = openinfo->reclen;
  117.             if (t->bt_reclen == 0)
  118.                 goto einval;
  119.         }
  120.         t->bt_bval = openinfo->bval;
  121.     } else
  122.         t->bt_bval = '\n';
  123.  
  124.     SET(t, R_RECNO);
  125.     if (fname == NULL)
  126.         SET(t, R_EOF | R_INMEM);
  127.     else
  128.         t->bt_rfd = rfd;
  129.     t->bt_rcursor = 0;
  130.  
  131.     /*
  132.      * In 4.4BSD stat(2) returns true for ISSOCK on pipes.  Until
  133.      * then, this is fairly close.  Pipes are read-only.
  134.      */
  135.     if (fname != NULL) {
  136.         if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
  137.             switch (flags & O_ACCMODE) {
  138.             case O_RDONLY:
  139.                 SET(t, R_RDONLY);
  140.                 break;
  141.             default:
  142.                 goto einval;
  143.             }
  144. slow:        if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
  145.                 goto err;
  146.             SET(t, R_CLOSEFP);
  147.             t->bt_irec =
  148.                 ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
  149.         } else {
  150.             switch (flags & O_ACCMODE) {
  151.             case O_RDONLY:
  152.                 SET(t, R_RDONLY);
  153.                 break;
  154.             case O_RDWR:
  155.                 break;
  156.             default:
  157.                 goto einval;
  158.             }
  159.  
  160.             if (fstat(rfd, &sb))
  161.                 goto err;
  162.             /*
  163.              * Kluge -- we'd like to test to see if the file is too
  164.              * big to mmap.  Since, we don't know what size or type
  165.              * off_t's or size_t's are, what the largest unsigned
  166.              * integral type is, or what random insanity the local
  167.              * C compiler will perpetrate, doing the comparison in
  168.              * a portable way is flatly impossible.  Hope that mmap
  169.              * fails if the file is too large.
  170.              */
  171.             if (sb.st_size == 0)
  172.                 SET(t, R_EOF);
  173.             else {
  174.                 t->bt_msize = sb.st_size;
  175. #ifdef macintosh
  176.                 goto slow;
  177. #else
  178.                 if ((t->bt_smap =
  179.                     mmap(NULL, t->bt_msize, PROT_READ, 0, rfd,
  180.                     (off_t)0)) == (caddr_t)-1)
  181.                     goto slow;
  182.                 t->bt_cmap = t->bt_smap;
  183.                 t->bt_emap = t->bt_smap + sb.st_size;
  184.                 t->bt_irec = ISSET(t, R_FIXLEN) ?
  185.                     __rec_fmap : __rec_vmap;
  186.                 SET(t, R_MEMMAPPED);
  187. #endif
  188.             }
  189.         }
  190.     }
  191.  
  192.     /* Use the recno routines. */
  193.     dbp->close = __rec_close;
  194.     dbp->del = __rec_delete;
  195.     dbp->fd = __rec_fd;
  196.     dbp->get = __rec_get;
  197.     dbp->put = __rec_put;
  198.     dbp->seq = __rec_seq;
  199.     dbp->sync = __rec_sync;
  200.  
  201.     /* If the root page was created, reset the flags. */
  202.     if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
  203.         goto err;
  204.     if ((h->flags & P_TYPE) == P_BLEAF) {
  205.         h->flags = h->flags & ~P_TYPE | P_RLEAF;
  206.         mpool_put(t->bt_mp, h, MPOOL_DIRTY);
  207.     } else
  208.         mpool_put(t->bt_mp, h, 0);
  209.  
  210.     if (openinfo && openinfo->flags & R_SNAPSHOT &&
  211.         !ISSET(t, R_EOF | R_INMEM) &&
  212.         t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
  213.                 goto err;
  214.     return (dbp);
  215.  
  216. einval:    errno = EINVAL;
  217. err:    sverrno = errno;
  218.     if (dbp != NULL)
  219.         (void)__bt_close(dbp);
  220.     if (fname != NULL)
  221.         (void)close(rfd);
  222.     errno = sverrno;
  223.     return (NULL);
  224. }
  225.  
  226. int
  227. __rec_fd(dbp)
  228.     const DB *dbp;
  229. {
  230.     BTREE *t;
  231.  
  232.     t = dbp->internal;
  233.  
  234.     if (ISSET(t, R_INMEM)) {
  235.         errno = ENOENT;
  236.         return (-1);
  237.     }
  238.     return (t->bt_rfd);
  239. }
  240.